package com.example.exceldemo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.exceldemo.dao.DocGenerationFileDao;
import com.example.exceldemo.dao.DocGenerationTaskDao;
import com.example.exceldemo.model.DocGenerationFile;
import com.example.exceldemo.model.DocGenerationTask;
import com.example.exceldemo.model.DocGenerationTask.TaskStatus;
import com.example.exceldemo.model.PageResult;
import com.example.exceldemo.model.dto.TaskQueryDTO;
import com.example.exceldemo.service.DocTaskService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

/**
 * 文档任务服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DocTaskServiceImpl implements DocTaskService {
    
    private final DocGenerationTaskDao taskDao;
    private final DocGenerationFileDao fileDao;
    private final ObjectMapper objectMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createTask(String filePath, List<String> selectedReqs) {
        try {
            // 生成任务ID
            String taskId = generateTaskId();
            log.info("开始创建任务: {}, 文件路径: {}, 选择需求数: {}", taskId, filePath, selectedReqs.size());
            
            DocGenerationTask task = new DocGenerationTask()
                    .setTaskId(taskId)
                    .setFilePath(filePath)
                    .setStatus(TaskStatus.PENDING.name())
                    .setProgress(0)
                    .setCreateTime(LocalDateTime.now());
            
            // 将选择的需求ID列表转换为JSON字符串
            try {
                task.setSelectedReqs(objectMapper.writeValueAsString(selectedReqs));
            } catch (JsonProcessingException e) {
                log.error("转换选择的需求ID列表为JSON失败", e);
                task.setSelectedReqs("[]"); // 设置一个默认值避免NULL
            }
            
            log.info("准备插入任务到数据库: {}", task);
            int result = taskDao.insert(task);
            if (result <= 0) {
                log.error("任务插入失败，影响行数为0: {}", taskId);
                throw new RuntimeException("任务插入数据库失败");
            }
            
            log.info("任务创建成功: {}, 影响行数: {}", taskId, result);
            
            // 插入后立即查询验证
            DocGenerationTask savedTask = getTask(taskId);
            if (savedTask == null) {
                log.warn("任务已插入但无法立即查询到，可能是事务尚未提交: {}", taskId);
            } else {
                log.info("任务创建后查询验证成功: {}", taskId);
            }
            
            return taskId;
        } catch (Exception e) {
            log.error("创建任务过程中发生异常", e);
            throw new RuntimeException("创建任务失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskStatus(String taskId, String status, Integer progress, String outputDir, String errorMsg) {
        try {
            log.info("开始更新任务状态: {}, 状态: {}, 进度: {}", taskId, status, progress);
            
            DocGenerationTask task = new DocGenerationTask()
                    .setTaskId(taskId)
                    .setStatus(status)
                    .setProgress(progress)
                    .setOutputDir(outputDir)
                    .setErrorMessage(errorMsg);
            
            // 任务完成或失败时，设置完成时间
            if (TaskStatus.COMPLETED.name().equals(status) || TaskStatus.FAILED.name().equals(status)) {
                task.setCompleteTime(LocalDateTime.now());
            }
            
            LambdaQueryWrapper<DocGenerationTask> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DocGenerationTask::getTaskId, taskId);
            int result = taskDao.update(task, wrapper);
            
            if (result <= 0) {
                log.warn("更新任务状态时未影响任何行，任务可能不存在: {}", taskId);
            } else {
                log.info("任务状态更新成功: {}", taskId);
            }
        } catch (Exception e) {
            log.error("更新任务状态过程中发生异常: {}", taskId, e);
            throw new RuntimeException("更新任务状态失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public DocGenerationTask getTask(String taskId) {
        try {
            log.debug("查询任务: {}", taskId);
            LambdaQueryWrapper<DocGenerationTask> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DocGenerationTask::getTaskId, taskId);
            DocGenerationTask task = taskDao.selectOne(wrapper);
            if (task == null) {
                log.debug("未找到任务: {}", taskId);
            }
            return task;
        } catch (Exception e) {
            log.error("查询任务过程中发生异常: {}", taskId, e);
            return null;
        }
    }
    
    @Override
    public PageResult<DocGenerationTask> listTasks(TaskQueryDTO queryDTO) {
        try {
            log.info("开始查询任务列表: 页码={}, 每页大小={}, 状态={}, 任务ID={}", 
                    queryDTO.getPageNum(), queryDTO.getPageSize(), queryDTO.getStatus(), queryDTO.getTaskId());
            
            LambdaQueryWrapper<DocGenerationTask> wrapper = new LambdaQueryWrapper<>();
            
            // 任务ID条件（支持模糊查询）
            if (queryDTO.getTaskId() != null && !queryDTO.getTaskId().isEmpty()) {
                wrapper.like(DocGenerationTask::getTaskId, queryDTO.getTaskId());
                log.debug("添加任务ID模糊查询条件: {}", queryDTO.getTaskId());
            }
            
            // 状态条件
            if (queryDTO.getStatus() != null && !queryDTO.getStatus().isEmpty()) {
                wrapper.eq(DocGenerationTask::getStatus, queryDTO.getStatus());
                log.debug("添加状态查询条件: {}", queryDTO.getStatus());
            }
            
            // 时间范围条件
            if (queryDTO.getStartTime() != null && !queryDTO.getStartTime().isEmpty()) {
                wrapper.ge(DocGenerationTask::getCreateTime, queryDTO.getStartTime());
                log.debug("添加开始时间查询条件: {}", queryDTO.getStartTime());
            }
            
            if (queryDTO.getEndTime() != null && !queryDTO.getEndTime().isEmpty()) {
                wrapper.le(DocGenerationTask::getCreateTime, queryDTO.getEndTime());
                log.debug("添加结束时间查询条件: {}", queryDTO.getEndTime());
            }
            
            // 按创建时间降序排序
            wrapper.orderByDesc(DocGenerationTask::getCreateTime);

            // 设置分页参数
            int pageNum = queryDTO.getPageNum() != null ? queryDTO.getPageNum() : 1;
            int pageSize = queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10;

            log.debug("执行分页查询: 页码={}, 每页大小={}", pageNum, pageSize);
            
            // 创建分页对象
            com.baomidou.mybatisplus.extension.plugins.pagination.Page<DocGenerationTask> page =
                new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNum, pageSize);

            // 执行查询
            com.baomidou.mybatisplus.extension.plugins.pagination.Page<DocGenerationTask> resultPage =
                taskDao.selectPage(page, wrapper);
            
            List<DocGenerationTask> records = resultPage.getRecords();
            long total = resultPage.getTotal();
            
            log.info("查询任务列表完成: 找到{}条记录", total);
            
            if (records.isEmpty()) {
                log.warn("未找到任何任务记录");
                // 尝试一次不带条件的查询，验证表中是否有数据
                long count = taskDao.selectCount(null);
                log.info("数据库中总共有{}条任务记录", count);
            } else {
                log.debug("第一条记录ID: {}, 状态: {}", records.get(0).getTaskId(), records.get(0).getStatus());
            }

            return PageResult.of(records, pageNum, pageSize, (int) total);
        } catch (Exception e) {
            log.error("分页查询任务列表过程中发生异常", e);
            return PageResult.empty(queryDTO.getPageNum(), queryDTO.getPageSize());
        }
    }
    
    @Override
    public List<DocGenerationFile> listTaskFiles(String taskId) {
        try {
            LambdaQueryWrapper<DocGenerationFile> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DocGenerationFile::getTaskId, taskId);
            return fileDao.selectList(wrapper);
        } catch (Exception e) {
            log.error("查询任务文件列表过程中发生异常: {}", taskId, e);
            return java.util.Collections.emptyList();
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recordFile(String taskId, String reqNo, String reqName, String filePath, Long fileSize, String fileType) {
        try {
            log.info("记录文件信息: 任务ID={}, 需求号={}, 文件路径={}", taskId, reqNo, filePath);
            
            DocGenerationFile file = new DocGenerationFile()
                    .setTaskId(taskId)
                    .setReqNo(reqNo)
                    .setReqName(reqName)
                    .setFilePath(filePath)
                    .setFileSize(fileSize)
                    .setFileType(fileType)
                    .setCreateTime(LocalDateTime.now());
            
            int result = fileDao.insert(file);
            if (result <= 0) {
                log.error("文件记录插入失败: {}", filePath);
                throw new RuntimeException("文件记录插入数据库失败");
            }
            
            log.info("文件记录成功: {}", filePath);
        } catch (Exception e) {
            log.error("记录文件信息过程中发生异常", e);
            throw new RuntimeException("记录文件信息失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recordFiles(List<DocGenerationFile> files) {
        try {
            log.info("批量记录文件信息，数量: {}", files.size());
            
            for (DocGenerationFile file : files) {
                file.setCreateTime(LocalDateTime.now());
                int result = fileDao.insert(file);
                if (result <= 0) {
                    log.error("批量文件记录中某条插入失败: {}", file.getFilePath());
                }
            }
            
            log.info("批量文件记录完成");
        } catch (Exception e) {
            log.error("批量记录文件信息过程中发生异常", e);
            throw new RuntimeException("批量记录文件信息失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 生成任务ID
     */
    private String generateTaskId() {
        return UUID.randomUUID().toString().replace("-", "");
    }
} 